import logging
from typing import Dict, Any, List, Optional
from src.tools.mcp_client import create_mcp_connection, MCPClient
from config import config

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class JiraConnector:
    """
    Jira Connector that uses MCP Client as the underlying communication layer.
    Provides Jira-specific operations by calling MCP tools.
    """
    
    def __init__(self, transport: str = "sse"):
        self.transport = transport
        self.mcp_client: Optional[MCPClient] = None
        logger.info("JiraConnector initialized")
    
    async def connect(self) -> bool:
        """
        Establish connection to MCP server.
        """
        try:
             # 如果已经连接，直接返回
            if self.mcp_client and self.mcp_client.is_connected:
                return True
            
            self.mcp_client = await create_mcp_connection(
                server_url=config.mcp_url,
                api_key=config.mcp_api_key or None
            )
            logger.info("Successfully connected to MCP server")
            return True
        except Exception as e:
            logger.error(f"Failed to connect to MCP server: {str(e)}")
            return False
    
    async def initialize_connection(self) -> Dict[str, Any]:
        """
        Initialize connection to Jira MCP server.
        """
        try:
            if not self.mcp_client:
                connected = await self.connect()
                if not connected:
                    return {"status": "error", "message": "Failed to connect to MCP server"}
            
            # Connection is already initialized in create_mcp_connection
            return {"status": "success", "message": "Connection already initialized"}
        except Exception as e:
            logger.error(f"Error initializing connection: {str(e)}")
            return {"status": "error", "error": str(e)}
    
    def list_tools(self) -> List[Dict[str, Any]]:
        """
        List available Jira tools from MCP server.
        """
        try:
            if not self.mcp_client or not self.mcp_client.is_connected:
                return [{"status": "error", "message": "Not connected to MCP server"}]
            
            tools = self.mcp_client.tools
            # Filter only Jira-related tools
            # 正确格式化工具信息
            tool_list = [
                {
                    "name": tool.name,
                    "description": tool.description,
                }
                for tool in tools if hasattr(tool, 'name') and hasattr(tool, 'description')
            ]
            return tool_list
        except Exception as e:
            logger.error(f"Error listing tools: {str(e)}")
            return [{"status": "error", "error": str(e)}]
    
    def execute_tool_sync(self, tool_name: str, parameters: Dict[str, Any]) -> Dict[str, Any]:
        """
        同步执行工具的方法，完全避免异步调用
        """
        import asyncio
        import concurrent.futures
        
        logger.info(f"Executing tool {tool_name} synchronously with parameters {parameters}")
        
        def run_in_thread():
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            try:
                # 在这个线程中创建全新的 MCP 客户端连接
                async def create_connection_and_execute():
                    try:
                        # 创建全新的 MCP 客户端，避免使用任何已存在的连接
                        mcp_client = await create_mcp_connection(
                            server_url=config.mcp_url,
                            api_key=config.mcp_api_key or None
                        )
                        
                        # 确保工具名称正确
                        actual_tool_name = tool_name
                        if not tool_name.startswith("jira_"):
                            actual_tool_name = f"jira_{tool_name}"
                        
                        logger.info(f"Calling MCP tool: {actual_tool_name}")
                        result = await mcp_client.call_tool(actual_tool_name, parameters)
                        
                        # 关闭连接
                        if hasattr(mcp_client, 'close'):
                            await mcp_client.close()
                        
                        return {"status": "success", "result": result}
                        
                    except Exception as e:
                        logger.error(f"Error in create_connection_and_execute: {str(e)}")
                        return {"status": "error", "error": str(e)}
                
                # 执行所有操作
                return loop.run_until_complete(create_connection_and_execute())
                
            except Exception as e:
                logger.error(f"Error in thread execution: {str(e)}")
                return {"status": "error", "error": str(e)}
            finally:
                # 确保事件循环被正确关闭
                try:
                    loop.close()
                except:
                    pass
        
        with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
            future = executor.submit(run_in_thread)
            try:
                return future.result(timeout=30)
            except concurrent.futures.TimeoutError:
                logger.error(f"Tool {tool_name} execution timed out")
                return {"status": "error", "error": "Operation timed out"}
            except Exception as e:
                logger.error(f"Error in thread pool execution: {str(e)}")
                return {"status": "error", "error": str(e)}

    async def execute_tool(self, tool_name: str, parameters: Dict[str, Any]) -> Dict[str, Any]:
        """
        Execute a specific Jira tool via MCP.
        
        Args:
            tool_name: Name of the tool to execute (e.g., 'jira_create_issue')
            parameters: Parameters for the tool
            
        Returns:
            Result of the tool execution
        """
        logger.info(f"Executing tool {tool_name} with parameters {parameters}")
        try:
            if not self.mcp_client:
                connected = await self.connect()
                if not connected:
                    return {"status": "error", "message": "Failed to connect to MCP server"}
            
            if not self.mcp_client.is_connected:
                return {"status": "error", "message": "Not connected to MCP server"}
            
            # Ensure it's a Jira tool
            if not tool_name.startswith("jira_"):
                tool_name = f"jira_{tool_name}"
            
            result = await self.mcp_client.call_tool(tool_name, parameters)
            return {"status": "success", "result": result}
        except Exception as e:
            logger.error(f"Error executing tool {tool_name}: {str(e)}")
            return {"status": "error", "error": str(e)}
    
    async def create_issue(self, summary: str, description: str, project_key: str, 
                          issue_type: str = "Task", **kwargs) -> Dict[str, Any]:
        """
        Create a new Jira issue.
        """
        params = {
            "summary": summary,
            "description": description,
            "project_key": project_key,
            "issue_type": issue_type,
            **kwargs
        }
        return await self.execute_tool("jira_create_issue", params)
    
    async def get_issue(self, issue_key: str) -> Dict[str, Any]:
        """
        Get details of a Jira issue.
        """
        return await self.execute_tool("jira_get_issue", {"issue_key": issue_key})
    
    async def update_issue(self, issue_key: str, fields: Dict[str, Any]) -> Dict[str, Any]:
        """
        Update an existing Jira issue.
        """
        params = {
            "issue_key": issue_key,
            "fields": fields
        }
        return await self.execute_tool("jira_update_issue", params)
    
    async def search_issues(self, jql: str, max_results: int = 50) -> Dict[str, Any]:
        """
        Search for Jira issues using JQL.
        """
        params = {
            "jql": jql,
            "max_results": max_results
        }
        return await self.execute_tool("jira_search_issues", params)